home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / SmallTalk / Metaclass.st < prev    next >
Text File  |  1995-08-25  |  9KB  |  290 lines

  1. "======================================================================
  2. |
  3. |   MetaClass Method Definitions
  4. |
  5.  ======================================================================"
  6.  
  7.  
  8. "======================================================================
  9. |
  10. | Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  11. | Written by Steve Byrne.
  12. |
  13. | This file is part of GNU Smalltalk.
  14. |
  15. | GNU Smalltalk is free software; you can redistribute it and/or modify it
  16. | under the terms of the GNU General Public License as published by the Free
  17. | Software Foundation; either version 1, or (at your option) any later version.
  18. | GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
  19. | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  20. | FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
  21. | details.
  22. | You should have received a copy of the GNU General Public License along with
  23. | GNU Smalltalk; see the file COPYING.  If not, write to the Free Software
  24. | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
  25. |
  26.  ======================================================================"
  27.  
  28.  
  29. "
  30. |     Change Log
  31. | ============================================================================
  32. | Author       Date       Change 
  33. | sbyrne     16 May 90      Changed the implementation of name: ... to try to
  34. |              preserve an existing class (if possible).  The
  35. |              original code exists in newMeta: ...
  36. |
  37. | sbyrne     25 Apr 89      created.
  38. |
  39. "
  40.  
  41. ClassDescription subclass: #Metaclass
  42.          instanceVariableNames: 'instanceClass'
  43.          classVariableNames: ''
  44.          poolDictionaries: ''
  45.          category: nil
  46. !
  47.  
  48. Metaclass comment: 
  49. 'I am the root of the class hierarchy.  My instances are metaclasses, one for
  50. each real class.  My instances have a single instance, which they hold
  51. onto, which is the class that they are the metaclass of.  I provide methods
  52. for creation of actual class objects from metaclass object, and the creation
  53. of metaclass objects, which are my instances.  If this is confusing to you,
  54. it should be...the Smalltalk metaclass system is strange and complex.' !
  55.  
  56. !Metaclass class methodsFor: 'instance creation'!
  57.  
  58. subclassOf: superMeta
  59.     | newMeta |
  60.     newMeta _ self new.
  61.     newMeta superclass: superMeta.
  62.     superMeta addSubclass: newMeta.
  63.     newMeta initMetaclass.
  64.     ^newMeta
  65.  
  66. !!
  67.  
  68.  
  69.  
  70. !Metaclass methodsFor: 'basic'!
  71.  
  72. name: newName
  73.     environment: aSystemDictionary
  74.     subclassOf: superclass
  75.     instanceVariableNames: stringOfInstVarNames
  76.     variable: variableBoolean
  77.     words: wordBoolean
  78.     pointers: pointerBoolean
  79.     classVariableNames: stringOfClassVarNames
  80.     poolDictionaries: stringOfPoolNames
  81.     category: categoryName
  82.     comment: commentString
  83.     changed: changed
  84.     | aClass variableString variableArray sharedPoolNames poolName pool 
  85.       className classVarDict oldClassPool |
  86.  
  87.     "Please don't look at this case for an example of how to create good 
  88.      Smalltalk code.  It is inelegantly written and probably highly 
  89.     inefficient."
  90.  
  91.     className _ newName asSymbol.
  92.     aClass _ aSystemDictionary at: className ifAbsent: [ nil ].
  93.     aClass isNil
  94.     ifTrue: [ ^self newMeta: newName
  95.             environment: aSystemDictionary
  96.             subclassOf: superclass
  97.             instanceVariableNames: stringOfInstVarNames
  98.             variable: variableBoolean
  99.             words: wordBoolean
  100.             pointers: pointerBoolean
  101.             classVariableNames: stringOfClassVarNames
  102.             poolDictionaries: stringOfPoolNames
  103.             category: categoryName
  104.             comment: commentString
  105.             changed: changed ].
  106.  
  107.     (aClass isVariable == variableBoolean)
  108.     & (aClass isWords == wordBoolean )
  109.     & (aClass isPointers == pointerBoolean)
  110.     ifFalse: [ ^self newMeta: newName
  111.               environment: aSystemDictionary
  112.               subclassOf: superclass
  113.               instanceVariableNames: stringOfInstVarNames
  114.               variable: variableBoolean
  115.               words: wordBoolean
  116.               pointers: pointerBoolean
  117.               classVariableNames: stringOfClassVarNames
  118.               poolDictionaries: stringOfPoolNames
  119.               category: categoryName
  120.               comment: commentString
  121.               changed: changed ].
  122.  
  123.     "Here we have an existing class, so try hard to leave it alone"
  124.     instanceClass _ aClass.
  125.     aClass setSuperclass: superclass.
  126.     " Fix up meta class link also "
  127.     superclass notNil
  128.     ifTrue: [ aClass class setSuperclass: superclass class ].
  129.  
  130.     superclass notNil 
  131.     ifTrue: [ "Inherit instance variables from parent"
  132.               variableString _ superclass instanceVariableString
  133.           ]
  134.         ifFalse: [ variableString _ '' ].
  135.     variableString _ variableString , stringOfInstVarNames.
  136.     variableArray _ self parseVariableString: variableString.
  137.     1 to: variableArray size do:
  138.         [ :i | variableArray at: i put: (variableArray at: i) asSymbol ].
  139.     variableArray = aClass allInstVarNames
  140.     ifFalse: [ stdout nextPutAll: 'Recompilation required!'; nl.
  141.            "aClass compileAll.
  142.            aClass compileAllSubclasses."
  143.            "### This should be fixed soon" ].
  144.     aClass setInstanceVariables: variableArray.
  145.  
  146.     aClass setInstanceSpec: variableBoolean words: wordBoolean
  147.         pointers: pointerBoolean instVars: variableArray size.
  148.  
  149.     classVarDict _ (self parseToDict: stringOfClassVarNames).
  150.     oldClassPool _ aClass classPool.
  151.     oldClassPool isNil 
  152.     ifTrue: [ aClass setClassVariables: classVarDict ]
  153.     ifFalse: [ classVarDict associationsDo:
  154.                [ :assoc | (oldClassPool includesKey: assoc key)
  155.                       ifFalse: 
  156.                       [ aClass addClassVarName: 
  157.                         assoc key ] ] ].
  158.     classVarDict keys  ~= aClass classPool keys
  159.     ifTrue: [ stdout nextPutAll:
  160.               'Recompilation required: different class variables!';
  161.                         nl ].
  162.  
  163.     sharedPoolNames _ self parseVariableString: stringOfPoolNames.
  164.     1 to: sharedPoolNames size do:
  165.         [ :i | poolName _ (sharedPoolNames at: i) asSymbol.
  166.                "### Check that the pool name starts with an uppercase letter
  167.         here."
  168.            "??? Should this create the pool if not there?"
  169.            pool _ aSystemDictionary
  170.                        at: poolName
  171.                        ifAbsent: [ ^self error: 'Pool name ', poolName ,
  172.                                      ' does not exist' ].
  173.               sharedPoolNames at: i put: pool ].
  174.     "### probably should check for recompilation required here in case
  175.      the intersection of the sets of pool dictionaries shrinks"
  176.     aClass setSharedPools: sharedPoolNames.
  177.  
  178.     "### not done"
  179.     aClass category: categoryName. "### need to remove the old category maybe"
  180.     "### don't know what to do with changed"
  181.     "### Need to update existing meta class (if there is one) -- change
  182.      its superclass, and fixup its old superclass to not refer to it
  183.      anymore"
  184.     ^aClass
  185. !
  186.  
  187.  
  188. newMeta: newName
  189.     environment: aSystemDictionary
  190.     subclassOf: superclass
  191.     instanceVariableNames: stringOfInstVarNames
  192.     variable: variableBoolean
  193.     words: wordBoolean
  194.     pointers: pointerBoolean
  195.     classVariableNames: stringOfClassVarNames
  196.     poolDictionaries: stringOfPoolNames
  197.     category: categoryName
  198.     comment: commentString
  199.     changed: changed
  200.     | aClass variableString variableArray sharedPoolNames poolName pool |
  201.  
  202.     sharedPoolNames _ self parseVariableString: stringOfPoolNames.
  203.     1 to: sharedPoolNames size do:
  204.         [ :i | poolName _ (sharedPoolNames at: i) asSymbol.
  205.            (poolName at: 1) isUppercase
  206.            ifFalse: [ ^self error: 'Pool name ', poolName,
  207.                   ' does not begin with an uppercase letter' ].
  208.            pool _ aSystemDictionary at: poolName
  209.                        ifAbsent: [ ^self error: 'Pool name ', poolName ,
  210.                     ' does not exist' ].
  211.               sharedPoolNames at: i put: pool ].
  212.     aClass _ self new.
  213.     instanceClass _ aClass.
  214.     aSystemDictionary at: (newName asSymbol) put: aClass.
  215.     aClass superclass: superclass.
  216.     aClass setName: newName asSymbol.
  217.     superclass notNil
  218.         ifTrue: [ superclass addSubclass: aClass.
  219.                   "Inherit instance variables from parent"
  220.               variableString _ superclass instanceVariableString
  221.           ]
  222.         ifFalse: [ variableString _ '' ].
  223.     variableString _ variableString , stringOfInstVarNames.
  224.     variableArray _ self parseVariableString: variableString.
  225.     1 to: variableArray size do:
  226.         [ :i | variableArray at: i put: (variableArray at: i) asSymbol ].
  227.     aClass setInstanceVariables: variableArray.
  228.     aClass setInstanceSpec: variableBoolean words: wordBoolean
  229.         pointers: pointerBoolean instVars: variableArray size.
  230.     aClass setClassVariables: (self parseToDict: stringOfClassVarNames).
  231.     aClass setSharedPools: sharedPoolNames.
  232.     "### not done"
  233.     aClass category: categoryName.
  234.     aClass comment: commentString.
  235.     "### don't know what to do with changed"
  236.     "### Need to update existing meta class (if there is one) -- change
  237.      its superclass, and fixup its old superclass to not refer to it
  238.      anymore"
  239.     ^aClass
  240. !!
  241.  
  242.  
  243.  
  244. !Metaclass methodsFor: 'accessing'!
  245.  
  246. instanceClass
  247.     ^instanceClass
  248. !!
  249.  
  250.  
  251.  
  252.  
  253. !Metaclass methodsFor: 'printing'!
  254.  
  255. printOn: aStream
  256.     instanceClass printOn: aStream.
  257.     aStream nextPutAll: ' class'
  258. !
  259.  
  260. storeOn: aStream
  261.     self printOn: aStream
  262. !!
  263.  
  264.  
  265.  
  266. !Metaclass methodsFor: 'private'!
  267.  
  268. initMetaclass
  269.     instanceVariables _ Class allInstVarNames.
  270.     instanceSpec _ Class instanceSpec
  271. !
  272.  
  273. parseVariableString: aString
  274.     | stream |
  275.     stream _ TokenStream on: aString.
  276.     ^stream contents
  277. !
  278.  
  279. parseToDict: aString
  280.     | tokenArray dict |
  281.     tokenArray _ self parseVariableString: aString.
  282.     dict _ Dictionary new.
  283.     tokenArray do:
  284.         [ :element | dict at: element asSymbol put: nil ].
  285.     ^dict
  286.  
  287. !!
  288.